#ifndef FORMAT_H
#define FORMAT_H

#include "message.hpp"
#include <memory>
#include <vector>
#include <unordered_set>

namespace Log
{

    /**
     * @brief 格式化项基类，定义接口用于将日志消息格式化为输出流
     * @note 所有具体格式化项需继承此类并实现format方法
     */
    class FormatItem
    {
    public:
        using ptr = std::shared_ptr<FormatItem>;

        virtual ~FormatItem() = default;

        /**
         * @brief 纯虚函数，子类需实现具体的格式化逻辑
         * @param out 输出流对象，用于累积格式化结果
         * @param msg 日志消息对象，包含所有日志信息
         */
        virtual void format(std::ostream &out, LogMessage &msg) = 0;
    };

    // ----------------------- 具体格式化项子类实现 -----------------------

    /**
     * @brief 消息体格式化项，输出日志的主体内容
     */
    class MsgFormatItem : public FormatItem
    {
        void format(std::ostream &out, LogMessage &msg) override
        {
            out << msg._payload; // 直接输出消息负载内容
        }
    };

    /**
     * @brief 日志级别格式化项，将枚举转换为可读字符串
     */
    class LevelFormatItem : public FormatItem
    {
        void format(std::ostream &out, LogMessage &msg) override
        {
            out << Log::LogLevel::toString(msg._level); // 使用转换函数获取级别字符串
        }
    };

    /**
     * @brief 时间格式化项，支持自定义strftime格式
     * @details 默认格式为"%H:%M:%S"，可通过构造参数指定格式
     */
    class TimeFormatItem : public FormatItem
    {
    public:
        /**
         * @brief 构造函数，初始化时间格式
         * @param fmt 时间格式字符串，遵循strftime规范
         */
        explicit TimeFormatItem(const std::string &fmt = "%H:%M:%S")
            : _time_fmt(fmt) {}

        void format(std::ostream &out, LogMessage &msg) override
        {
            struct tm t;
            localtime_r(&msg._ctime, &t); // 使用线程安全的时间转换
            char tmp[32] = {0};           // strftime要求缓冲区至少26字节，32保证安全
            strftime(tmp, 31, _time_fmt.c_str(), &t);
            out << tmp;
        }

    private:
        std::string _time_fmt; // 存储时间格式
    };

    /**
     * @brief 文件名格式化项，输出产生日志的源码文件名
     */
    class FileFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out, LogMessage &msg) override
        {
            out << msg._file;
        }
    };

    /**
     * @brief 行号格式化项，输出日志产生的代码行号
     */
    class LineFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out, LogMessage &msg) override
        {
            out << msg._line;
        }
    };

    /**
     * @brief 线程ID格式化项，输出日志产生的线程标识
     */
    class TIDFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out, LogMessage &msg) override
        {
            out << msg._tid;
        }
    };

    /**
     * @brief 日志器名称格式化项，输出日志器名称
     */
    class LoggerFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out, LogMessage &msg) override
        {
            out << msg._logger;
        }
    };

    /**
     * @brief 制表符格式化项，输出\\t用于格式对齐
     */
    class TabFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out, LogMessage & /*msg*/) override
        {
            out << '\t';
        }
    };

    /**
     * @brief 换行符格式化项，输出\\n用于换行
     */
    class NLineFormatItem : public FormatItem
    {
    public:
        void format(std::ostream &out, LogMessage & /*msg*/) override
        {
            out << '\n';
        }
    };

    /**
     * @brief 静态字符串格式化项，输出固定格式字符
     * @details 用于处理模式字符串中的非占位符内容（如方括号等）
     */
    class OtherFormatItem : public FormatItem
    {
    public:
        explicit OtherFormatItem(const std::string &str) : _str(str) {}

        void format(std::ostream &out, LogMessage & /*msg*/) override
        {
            out << _str;
        }

    private:
        std::string _str;
    };

    // ----------------------- 格式化器核心类 -----------------------

    /**
     * @brief 日志格式化器，根据模式字符串生成格式化输出
     * @details 模式语法：
     *   %d{fmt}   时间（使用strftime格式，默认%H:%M:%S）
     *   %t        线程ID
     *   %c        日志器名称
     *   %f        文件名
     *   %l        行号
     *   %p        日志级别
     *   %T        制表符
     *   %m        消息主体
     *   %n        换行符
     *   其他字符   原样输出
     *
     * @example "[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n" 对应格式：
     * [时间][线程ID][日志器名][文件名:行号][级别] 消息
     */
    class Formatter
    {
    public:
        using ptr = std::shared_ptr<Formatter>;
        /**
         * @brief 
         * @param pattern 格式化模式字符串，默认为标准格式
         */
        explicit Formatter(const std::string &pattern = "[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
            : _pattern(pattern)
        {
            // 构造时自动解析模式
            if (!parsePattern())
                throw "Formatted string parse error";
        }

        /**
         * @brief 格式化日志消息到输出流
         * @param out 目标输出流
         * @param msg 要格式化的日志消息
         */
        void format(std::ostream &out, LogMessage &msg)
        {
            for (auto &item : _items)
            {
                item->format(out, msg); // 遍历所有格式化项
            }
        }

        /**
         * @brief 格式化日志消息到字符串
         * @param msg 要格式化的日志消息
         * @return 格式化后的字符串结果
         */
        std::string format(LogMessage &msg)
        {
            std::stringstream ss;
            format(ss, msg);
            return ss.str();
        }

    private:
        /**
         * @brief 解析模式字符串，构建格式化项集合
         * @return 是否解析成功
         * @note 实现细节：逐字符解析模式字符串，处理转义和参数
         */
        bool parsePattern()
        {
            std::vector<std::pair<std::string, std::string>> fmt_order;
            const std::unordered_set<char> format_chars = {'d', 't', 'c', 'f', 'l', 'p', 'T', 'm', 'n'};

            size_t index = 0;
            std::string literal_str;

            while (index < _pattern.size())
            {
                literal_str.clear();
                while (index < _pattern.size() && _pattern[index] != '%')
                {
                    literal_str += _pattern[index++];
                }
                if (!literal_str.empty())
                {
                    fmt_order.emplace_back("", literal_str);
                }

                if (index >= _pattern.size())
                    break;

                size_t percent_count = 0;
                while (index < _pattern.size() && _pattern[index] == '%')
                {
                    ++percent_count;
                    ++index;
                }

                if (index >= _pattern.size() || !format_chars.count(_pattern[index]))
                {
                    fmt_order.emplace_back(std::make_pair("", std::string(percent_count, '%')));
                    continue;
                }

                const char fmt_char = _pattern[index++];
                std::string param;

                if (fmt_char == 'd' && index < _pattern.size() && _pattern[index] == '{')
                {
                    ++index;

                    while (index < _pattern.size() && _pattern[index] != '}')
                    {
                        param += _pattern[index++];
                    }

                    if (index >= _pattern.size())
                    {
                        throw std::runtime_error("Unclosed format parameter for %d: missing '}'");
                    }
                    ++index;
                }

                fmt_order.emplace_back(std::make_pair(std::string(1, fmt_char), param));
            }

            for (const auto &fmt : fmt_order)
            {
                if (fmt.first.empty())
                {
                    _items.push_back(std::make_shared<OtherFormatItem>(fmt.second));
                }
                else
                {
                    _items.push_back(createItem(fmt.first, fmt.second));
                }
            }

            return true;
        }

        /**
         * @brief 创建具体格式化项
         * @param key 格式化标识符（如d、t等）
         * @param val 格式化参数（如时间格式）
         * @return 格式化项智能指针
         */
        FormatItem::ptr createItem(const std::string &key, const std::string &val)
        {
            if (key == "d")
                return std::make_shared<TimeFormatItem>(val);
            if (key == "t")
                return std::make_shared<TIDFormatItem>();
            if (key == "c")
                return std::make_shared<LoggerFormatItem>();
            if (key == "f")
                return std::make_shared<FileFormatItem>();
            if (key == "l")
                return std::make_shared<LineFormatItem>();
            if (key == "p")
                return std::make_shared<LevelFormatItem>();
            if (key == "T")
                return std::make_shared<TabFormatItem>();
            if (key == "m")
                return std::make_shared<MsgFormatItem>();
            if (key == "n")
                return std::make_shared<NLineFormatItem>();
            return std::make_shared<OtherFormatItem>(val);
        }

    private:
        std::string _pattern;                // 原始模式字符串
        std::vector<FormatItem::ptr> _items; // 格式化项集合
    };
}

#endif